#!/bin/bash
#
# Copyright(c) 2012-2021 Intel Corporation
# SPDX-License-Identifier: BSD-3-Clause
#

. $(dirname $3)/conf_framework

check() {
	cur_name=$(basename $2)
	config_file_path=$1
	if compile_module $cur_name "bio_start_io_acct(NULL)" "linux/blkdev.h"
	then
        echo $cur_name "1" >> $config_file_path
	elif compile_module $cur_name "generic_start_io_acct(NULL, 0, 0, NULL)" "linux/bio.h"
	then
        echo $cur_name "2" >> $config_file_path
	elif compile_module $cur_name "generic_start_io_acct(0, 0, NULL)" "linux/bio.h"
	then
        echo $cur_name "3" >> $config_file_path
	elif compile_module $cur_name "part_round_stats(1, 1)" "linux/genhd.h"
	then
        echo $cur_name "4" >> $config_file_path
	elif compile_module $cur_name "part_round_stats(NULL, 1, 1)" "linux/genhd.h"
	then
        echo $cur_name "5" >> $config_file_path
    else
        echo $cur_name "X" >> $config_file_path
    fi
}

apply() {
    case "$1" in
    "1")
        add_function "
        static inline unsigned long long cas_generic_start_io_acct(
                struct bio *bio)
        {
            return bio_start_io_acct(bio);
        }"
    add_function "
        static inline void cas_generic_end_io_acct(
                struct bio *bio, unsigned long start_time)
        {
            bio_end_io_acct(bio, start_time);
        }" ;;
    "2")
        add_function "
        static inline unsigned long long cas_generic_start_io_acct(
                struct bio *bio)
        {
            struct gendisk *gd = CAS_BIO_GET_DEV(bio);

            generic_start_io_acct(gd->queue, bio_data_dir(bio),
                    bio_sectors(bio), &gd->part0);
            return jiffies;
        }"
    add_function "
        static inline void cas_generic_end_io_acct(
                struct bio *bio, unsigned long start_time)
        {
            struct gendisk *gd = CAS_BIO_GET_DEV(bio);

            generic_end_io_acct(gd->queue, bio_data_dir(bio),
                    &gd->part0, start_time);
        }" ;;
    "3")
        add_function "
        static inline unsigned long long cas_generic_start_io_acct(
                struct bio *bio)
        {
            struct gendisk *gd = CAS_BIO_GET_DEV(bio);

            generic_start_io_acct(bio_data_dir(bio), bio_sectors(bio),
                    &gd->part0);
            return jiffies;
        }"
    add_function "
        static inline void cas_generic_end_io_acct(
                struct bio *bio, unsigned long start_time)
        {
            struct gendisk *gd = CAS_BIO_GET_DEV(bio);

            generic_end_io_acct(bio_data_dir(bio), &gd->part0, start_time);
        }" ;;
    "4")
        add_function "
        static inline unsigned long long cas_generic_start_io_acct(
                struct bio *bio)
        {
            struct gendisk *gd = CAS_BIO_GET_DEV(bio);

            int rw = bio_data_dir(bio);
            int cpu = part_stat_lock();
            part_round_stats(cpu, part);
            part_stat_inc(cpu, part, ios[rw]);
            part_stat_add(cpu, part, sectors[rw], bio_sectors(bio));
            part_inc_in_flight(part, rw);
            part_stat_unlock();
            return jiffies;
        }"
    add_function "
        static inline void cas_generic_end_io_acct(
                struct bio *bio, unsigned long start_time)
        {
            struct gendisk *gd = CAS_BIO_GET_DEV(bio);

            int rw = bio_data_dir(bio);
            unsigned long duration = jiffies - start_time;
            int cpu = part_stat_lock();
            part_stat_add(cpu, &gd->part0, ticks[rw], duration);
            part_round_stats(cpu, &gd->part0);
            part_dec_in_flight(&gd->part0, rw);
            part_stat_unlock();
        }" ;;
    "5")
        add_function "
        static inline unsigned long long cas_generic_start_io_acct(
                struct bio *bio)
        {
            struct gendisk *gd = CAS_BIO_GET_DEV(bio);

            int rw = bio_data_dir(bio);
            int cpu = part_stat_lock();
            part_round_stats(NULL, cpu, &gd->part0);
            part_stat_inc(cpu, &gd->part0, ios[rw]);
            part_stat_add(cpu, &gd->part0, sectors[rw], bio_sectors(bio));
            part_inc_in_flight(NULL, &gd->part0, rw);
            part_stat_unlock();
            return jiffies;
        }"
    add_function "
        static inline void cas_generic_end_io_acct(
                struct bio *bio, unsigned long start_time)
        {
            struct gendisk *gd = CAS_BIO_GET_DEV(bio);

            int rw = bio_data_dir(bio);
            unsigned long duration = jiffies - start_time;
            int cpu = part_stat_lock();
            part_stat_add(cpu, &gd->part0, ticks[rw], duration);
            part_round_stats(NULL, cpu, &gd->part0);
            part_dec_in_flight(NULL, &gd->part0, rw);
            part_stat_unlock();
        }" ;;
    *)
        exit 1
        esac
}

conf_run $@
